home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************/
- /*
- C de Cerca 3
- Toolbox de Apple
- ResEdit
- Eventos
- Menú Archivo (Salir de la aplicación)
-
- Rafael Escoté - Enric Herrera
- BlauSoft S.L. para MacFormat España - 1996
-
- La descripción del código y la información sobre cómo preparar
- el entorno de programación y generar estos programas, está contenida
- en el ejemplar de MacFormat que los acompaña.
-
- */
- /*****************************************************************/
-
-
-
- /*
- LA TOOLBOX Y LOS FICHEROS 'UNIVERSAL HEADERS'
- ==============================================
- La Toolbox es una colección de funciones escritas por Apple
- que han sido ya compiladas y colocadas en los chips de ROM de cada
- Mac.
- Para poder emplear en nuestros programas una de dichas funciones,
- debemos informar al compilador acerca de los posibles parámetros
- y valores de salida requeridos.
- En otras palabras, el compilador necesita el prototipo de la función
- existente en la Toolbox de forma que pueda verificar que el uso que de
- ella hagamos en nuestro programa sea correcto.
- Los ficheros APPLE UNIVERSAL HEADERS proporcionados por Apple no
- son más que ficheros de texto conteniendo los prototipos de cada una de
- las funciones de la Toolbox.
-
- NOTA: Sólo para los más curiosos: En la carpeta que contiene el compilador,
- veréis una carpeta llamada 'MacOS Support' y en su interior una carpeta
- llamada 'Headers' y dentro de ella una carpeta llamada
- 'Universal Headers', que contiene todos los ficheros creados por Apple.
- */
-
-
-
- /*
- COMO DIFERENCIAR FUNCIONES PROPIAS Y DE LA TOOLBOX
- ===================================================
- A las funciones creadas por nosotros para este programa (y que por lo
- tanto no pertenecen a la Toolbox) les hemos dado nombres que comienzan
- por las iniciales MF. Por ejemplo, MF_PlaySnd(), MF_RandomColor() etc...
- Todas las restantes funciones que aparecen empleadas en el código, SON
- FUNCIONES PERTENECIENTES A LA TOOLBOX DE APPLE.
- (Una excepción: La función main() la hemos creado nosotros pero su nombre
- no puede ser otro que main(), por convención)
-
-
-
- /**************************************************************** */
- /* PROTOTIPOS DE LAS FUNCIONES QUE HEMOS CREADO */
- /* PARA NUESTRO PROGRAMA */
- /**************************************************************** */
- void main(void); /* Esta función NO puede tener otro nombre */
- void MF_InitToolbox (void);
- void MF_SetupMenus (void);
- void MF_AbreMiVentana (void);
- void MF_EscribeTexto (void);
- void MF_bucle_principal(void);
- void MF_MenuBar (long algoSeleccionado);
- void MF_Update (WindowPtr ventana_a_refrescar);
-
-
-
- /**************************************************************** */
- /* CONSTANTES Y VARIABLES GLOBALES */
- /* DE USO GENERAL */
- /**************************************************************** */
- Boolean gAcabarProg = false; /* Una variable global.
- Como siempre, las variables globales
- las prefijamos con la letra 'g'.
- Cuando gAcabarProg sea = true,
- acabaremos el programa */
-
-
-
- /**************************************************************** */
- /* CONSTANTES Y VARIABLES GLOBALES */
- /* RELACIONADAS CON LOS MENUS EN NUESTRO PROGRAMA */
- /**************************************************************** */
- /*
- Hemos editado el fichero CdeCerca_3.µ.rsrc creando en él un recurso nuevo
- de tipo MENU con el nº de identificación 129.
- Declaramos una constante con dicho valor para simplificar el código
- */
- #define kArchivoMenuID 129 /* Nuevo recurso 'MENU' para nuestro menú Archivo */
- #define kSalirItem 1 /* Nº de la opción 'Salir' en el menú Archivo */
-
- /*
- Crearemos un menú empleando las funciones de la Toolbox,
- GetMenu() e InsertMenu(). GetMenu() nos devuelve un handle (especie de puntero)
- al menú recién creado. Hemos de declarar pues, una variable adecuada...
- */
- MenuHandle gArchivoMenu; /* Nuestro menú archivo, una vez creado */
-
-
-
- /**************************************************************** */
- /* CONSTANTES Y VARIABLES GLOBALES */
- /* RELACIONADAS CON LA VENTANA QUE ABRIREMOS */
- /**************************************************************** */
- /* La ventana que abriremos será creada dinámicamente por medio de
- la función NewWindow() que nos devolverá un puntero a la estructura de
- la nueva ventana, Declaramos pues, una variable adecuada... */
-
- WindowPtr gMiVentana = nil;/* Variable de tipo 'pointer'.
- Puntero a una estructura
- de tipo WindowRecord definida por Apple
- en el fichero UNIVERSAL HEADER Windows.h
- y que corresponderá
- a la ventana que crearemos
- NOTA sólo para curiosos: De hecho,
- una variable WindowPtr apunta a la
- estructura GrafPort que forma parte de
- la estructura WindowRecord. */
-
-
-
- /*--------------------------------------------------------------------*/
- /*
- A PARTIR DE ESTE PUNTO, APARECE EL CODIGO DE LAS FUNCIONES CREADAS
- ESPECIFICAMENTE PARA ESTE PROGRAMA.
-
- */
- /*--------------------------------------------------------------------*/
-
-
-
- /**************************************************************** */
- /* main() */
- /**************************************************************** */
- /*
- Todos los programas en C poseen una función que debe llamarse main.
- (NO PERTENECE A LA TOOLBOX)
- Cuando un programa se pone en marcha, lo hace SIEMPRE ejecutando
- en primer lugar la función main().
- Es el punto de entrada a nuestra aplicación.
-
- Recibe: nada
- Que hace: Llama otras funciones que preparan la aplicación...
- Salida: void (nada)
- */
- void main (void)
- {
- /* Antes de hacer nada, debemos inicializar la Toolbox del Mac */
- /* Como sea que el procedimiento a seguir para inicializar la Toolbox */
- /* es casi siempre el mismo, hemos creado una función MF_InitToolbox()*/
- /* que contiene las llamadas estándar de inicialización */
-
- MF_InitToolbox();
-
- /* Ahora debemos preparar y mostrar la barra de menú, que contendrá */
- /* los menús propios de nuestra aplicación */
-
- MF_SetupMenus();
-
- /* Ahora empleamos una función se encargará de abrir una ventana */
- MF_AbreMiVentana();
-
- /* Una vez abierta la ventana, podemos escribir algo de texto en ella */
- MF_EscribeTexto();
-
- /* Y ya podemos entrar en el bucle principal, que se encargará de
- recoger e interpretar las acciones del usuario */
- MF_bucle_principal();
-
- /* Cuando el bucle principal haya terminado, será porque el usuario
- desea acabar el programa.
- Debemos liberar la memoria ocupada por nuestra ventana. */
- DisposeWindow(gMiVentana);
-
- /* Y ya está, al acabarse la función main(), el Sistema cerrará
- nuestra aplicación de forma automática */
-
- } /* Fin de main() y del programa */
-
-
-
- /**************************************************************** */
- /* MF_bucle_principal */
- /**************************************************************** */
- /*
- Recibe: nada
- Que hace: Entra en un bucle y espera que se produzca una acción (evento)
- Según cual sea este, reacciona llamando una de las funciones que
- hemos creado en esta demo.
- Salida: nada
- */
- void MF_bucle_principal(void)
- {
- /* Declaramos una variable del tipo EventRecord que llamaremos el_Evento */
- EventRecord el_Evento;
- /*
- Un EventRecord es una estructura declarada
- por Apple en el fichero UNIVERSAL HEADER
- Events.h y formada por las siguientes
- variables:
-
- struct EventRecord {
- EventKind what; (qué evento)
- UInt32 message; (datos del evento)
- UInt32 when; (cuando se produce)
- Point where; (coordenadas del evento)
- EventModifiers modifiers;(estado de las teclas
- especiales: CMD, Opt, etc...)
- };
- */
-
- WindowPtr la_ventana; /* Guardaremos un puntero que nos indicará en que
- ventana (si es el caso) se ha producido un evento */
-
-
- short zona_de_la_ventana; /* También guardaremos el código que indica
- la zona de la ventana en que se produce un evento
- si es del tipo mouseDown
- */
-
-
- Boolean hay_evento; /* valor de salida de la función WaitNextEvent */
- /* Lo ignoraremos en esta demo */
-
- while (gAcabarProg == false)
- /* Mientras la variable global gAcabarProg sea falsa, repetiremos este bucle */
- /* Cuando el usuario seleccione 'Salir' del menú Archivo, cambiaremos el */
- /* valor de gAcabarProg a true (cierto) */
- {
-
- hay_evento = WaitNextEvent(everyEvent, &el_Evento, 0L, 0L);
- /* WaitNextEvent es una función de la ToolBox que nos proporciona
- información acerca de las posibles acciones del usuario o eventos del
- Sistema. Para ello, 'llena' de información las variables de la estructura
- EventRecord (el_Evento, en nuestro caso) */
-
- switch(el_Evento.what) /* what nos indica qué evento hemos recibido */
- {
- case nullEvent:
- /* Ignoramos eventos nulos (ningún evento).*/
- break;
-
- case keyDown:
- /* Se ha pulsado una tecla. Comprobaremos si también se ha pulsado
- la tecla de CMD y si es así, llamaremos la función que responde
- a la selección de opciones de menú */
- if(el_Evento.modifiers & cmdKey) /* Tecla de CMD pulsada? */
- {
- MF_MenuBar(MenuKey( el_Evento.message & charCodeMask) ) ;
- }
- break;
-
- case autoKey:
- /* Ignoramos los eventos de repetición, generados al mantener
- pulsada una tecla */
- break;
-
- case mouseDown:
- /* clic del ratón en algún sitio...*/
- zona_de_la_ventana = FindWindow(el_Evento.where,&la_ventana);
- switch (zona_de_la_ventana)
- {
- case inDrag:/* clic en la barra de título. Para que el usuario */
- /* pueda arrastrar la ventana, simplemente hemos de */
- /* usar la función DragWindow() que se encarga del */
- /* proceso, hasta que se suelte el botón del ratón */
- DragWindow(la_ventana,el_Evento.where,&qd.screenBits.bounds);
- break;
-
- case inMenuBar: /* clic en la barra de menús */
- MF_MenuBar(MenuSelect(el_Evento.where));
- break;
-
- default:
- /* Ignoramos clics en otras zonas de la ventana */
- break;
- }
- break;
-
- case mouseUp:
- /* ignoraremos los eventos producidos al soltar el botón del ratón */
- break;
-
- case diskEvt:
- /* También ignoraremos los eventos producidos al insertar un disco */
- break;
-
- case updateEvt:
- /* Una ventana debe ser refrescada. Llamamos la función
- MF_Update, pasándole un puntero a la ventana en cuestión.
- La variable message de la estructura EventRecord, contiene
- dicho puntero, pero es necesario forzar (cast) su tipo al
- de WindowPtr
- */
- la_ventana = (WindowPtr)el_Evento.message;
- MF_Update( la_ventana );
- break;
-
- default:
- /* En cualquier otro caso, ignoramos el evento */
- break;
-
- } /* Fin de switch(el_Evento.what) */
-
- } /* Fin de while (gAcabarProg == false) */
-
-
- } /* Fin de la función MF_bucle_principal() */
-
-
-
- /**************************************************************** */
- /* MF_Update */
- /**************************************************************** */
- /*
- Esta función se emplea cuando MF_bucle_principal ha detectado un evento
- del tipo updateEvt. El sistema lo genera cuando una ventana activa
- es desplazada o cuando una ventana que no era la activa es activada.
- En estos casos, la zona de la ventana que permanecía
- oculta por otras ventanas debe ser refrescada, re-dibujando su contenido.
- El sistema controla todas las ventanas abiertas y genera un evento updateEvt
- cuando alguna zona de una ventana necesita ser refrescada.
-
- Recibe: un puntero a la ventana que debe ser refrescada.
- Que hace: Esta demo aprovecha la función MF_EscribeTexto(). Cuando la ventana
- necesita refrescarse, simplemente llamamos de nuevo MF_EscribeTexto()
- y la ventana se actualizará.
-
- Salida: void (nada)
- */
- void MF_Update( WindowPtr ventana_a_refrescar)
- {
-
- GrafPtr old_port; /* Declaración de una variable de tipo
- puntero (pointer) a un área gráfica */
-
- GetPort( &old_port ); /* Preservamos el área gráfica actual */
-
- SetPort( ventana_a_refrescar ); /* Cambiamos de área, seleccionando la
- correspondiente a la ventana que debe
- refrescarse */
-
- BeginUpdate( ventana_a_refrescar );
-
- /* Aqui deberíamos llamar las funciones adecuadas para re-dibujar los
- contenidos de nuestra ventana. En este caso re-escribimos un texto
- en la ventana
- */
-
- MF_EscribeTexto();
-
- EndUpdate( ventana_a_refrescar );
-
- SetPort( old_port ); /* recuperamos el área gráfica inicial */
-
- } /* Fin de MF_Update() */
-
-
-
- /**************************************************************** */
- /* MF_MenuBar */
- /**************************************************************** */
- /*
- Esta función reacciona cuando MF_bucle_principal ha detectado que el clic
- del ratón se ha producido en la barra de menús de nuestro programa.
-
- Recibe: una variable con la información del menu e item seleccionados
- Que hace: Actúa en función de la posible selección de un item de alguno
- de nuestros menús.
- Salida: void (nada)
- */
- void MF_MenuBar(long algoSeleccionado)
- {
- short Que_Menu;
- short Que_Opcion;
- short dummy;
- Str255 ItemName;
- GrafPtr oldPort;
-
- if(algoSeleccionado != 0L)
- {
- /* algoSeleccionado es un valor de tipo long (4 bytes)
- que contiene en los 2 bytes superiores el número de menú seleccionado
- y en los dos bytes inferiores, el número de la opción seleccionada
- de dicho menú.
- Para extraer ambos valores, emplearemos una funciones de la Toolbox,
- HiWord y LoWord que nos devolverán los valores que nos interesan */
-
- Que_Menu = HiWord(algoSeleccionado); /* 2 bytes superiores */
- Que_Opcion = LoWord(algoSeleccionado);/* 2 bytes inferiores */
-
- switch(Que_Menu)
- {
-
- case kArchivoMenuID: /* Menú Archivo (el único de momento) */
- switch(Que_Opcion)
- {
- case kSalirItem: /* Opción 'Salir' (nº 1) */
- gAcabarProg = true; /* IMPORTANTE: Cambiamos el valor de
- la variable global que nos indica
- que debemos finalizar el programa */
- break;
-
- } /* Fin de switch(Que_Opcion) */
-
- break;
- } /* Fin de switch(Que_Menu) */
-
- HiliteMenu(0);
-
- } /* Fin de if(algoSeleccionado != 0L) */
-
- } /* Fin de función MF_MenuBar() */
-
-
-
- /**************************************************************** */
- /* MF_InitToolbox */
- /**************************************************************** */
- /*
- Inicializa la Toolbox Macintosh. El orden de llamada a las diversas
- rutinas es significativo! No lo cambie.
-
- Recibe: nada
- Cambia: nada en la aplicación
- Salida: nada
- */
- void MF_InitToolbox (void)
- {
- InitGraf(&qd.thePort);
- InitFonts();
- FlushEvents(everyEvent,0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor(); /* La llamada a InitCursor() */
- /* ajusta el cursor a la flecha estándar */
- /* y lo hace visible */
-
- } /* Fin de MF_InitToolbox() */
-
-
-
- /**************************************************************** */
- /* MF_SetupMenus */
- /**************************************************************** */
- /*
- Inicializa y muestra los menús del programa. En esta versión, es de destacar
- que NO implementamos el acceso al menú Apple (el de la manzanita...)
- En posteriores ejemplos se mostrará como instalarlo y acceder a él.
-
- Requiere: Recurso de tipo MENU en el fichero CdeCerca_3.µ.rsrc
- En concreto el recurso MENU nº 129 (kArchivoMenuID=129)
- Recibe: nada
- Cambia: asigna valor a las globales e instala el menú en la barra de menús
- Salida: nada
- */
- void MF_SetupMenus(void)
- {
- /* Primero, leer el recurso de tipo MENU que contiene la propia aplicación */
- /* Para ello, usamos la función GetMenu() de la Toolbox, que sólo requiere */
- /* como parámetro, el nº del recurso. Lo hemos declarado en una constante, */
- /* kArchivoMenuID al principio del código */
- gArchivoMenu = GetMenu( kArchivoMenuID );
-
- /* Con el menú en memoria, instalarlo y mostrarlo es coser y cantar... */
- /* Sólo hay que ejecutar la función InsertMenu(), también de la Toolbox */
- /* pasándole como parámetro el valor devuelto por GetMenu() */
- InsertMenu(gArchivoMenu, 0);
-
- DrawMenuBar(); /* y por último, actualizamos la barra de menús para que */
- /* se reflejen los cambios que acabamos de hacer. */
-
- } /* Fin de MF_SetupMenus() */
-
-
-
- /**************************************************************** */
- /* MF_AbreMiVentana */
- /**************************************************************** */
- /*
- Abre la ventana (la única) de nuestro programa.
-
- Recibe: nada
- Que hace: Crea una ventana...
- Salida: void (nada)
- */
- void MF_AbreMiVentana(void)
- {
- /*
- Programando el Mac hay más de una forma de crear y mostrar una ventana.
-
- De momento vamos a emplear la función de la Toolbox llamada NewWindow()
- pasándole una serie de parámetros que describen las características
- de la ventana (tamaño, título, posición, etc...)
-
- El prototipo de NewWindow es:
-
- NewWindow(void *wStorage,
- const Rect *boundsRect,
- ConstStr255Param title,
- Boolean visible,
- short theProc,
- WindowRef behind,
- Boolean goAwayFlag,
- long refCon)
-
- De momento sólo comentaremos el significado de 4 parámetros que nos
- interesan especialmente:
-
- *boundsrect: Una variable de tipo Rect (rectángulo) que describe la
- posición y tamaño de la nueva ventana.
- title: Una cadena de caracteres que forma el título de la ventana.
- visible: Un valor de tipo booleano indicando la visibilidad de la ventana.
- true = visible. False = invisible.
- theProc: Tipo de ventana que deseamos, Podemos emplear una de las siguientes
- constantes, definidas por Apple en el fichero Windows.h de
- los Universal Headers:
- documentProc
- dBoxProc
- plainDBox
- altDBoxProc
- noGrowDocProc
- movableDBoxProc
- zoomDocProc
- zoomNoGrow
- rDocProc
- goAwayFlag: Otro valor booleano que indica si la ventana debe tener cuadro
- de cierre (true) o no (false).
-
- */
-
- /* Antes que nada, declarar una variable Rect y asignarle valores */
- /* Rect es una estructura que contiene cuatro variables de tipo short */
- /* llamadas top, left, bottom y right.
-
- top
- |
- v
- left--> +-----------------+
- | |
- | |
- | |
- | |
- +-----------------+ <-- right
- ^
- |
- bottom
-
-
- El rectángulo que definamos estará describiendo la posición y tamaño
- de la ventana que deseamos crear.
- */
-
- Rect miRectangulo = { 48, /* top */
- 8, /* left */
- 108, /* bottom */
- 250 /* right */
- };
-
- gMiVentana = NewWindow( nil,
- &miRectangulo, /* Puntero al rectángulo */
- "\pC de Cerca - 3", /* Título */
- true, /* visible */
- documentProc, /* Cambie el tipo de ventana */
- /* para experimentar... */
- (WindowPtr)-1L,
- false, /* Sin cuadro de cierre */
- nil);
-
- if(gMiVentana == nil)
- ExitToShell(); /* Si la creación de la ventana falla,
- posiblemente sea debido a falta de memoria libre
- Lo más aconsejable es salir de la aplicación */
-
- } /* Fin de MF_AbreMiVentana() */
-
-
-
- /****************************************************************/
- /* MF_EscribeTexto */
- /****************************************************************/
- /*
- Dibuja en nuestra ventana un texto.
-
- Recibe: Nada
- Cambia: Dibuja en la ventana un texto.
- Salida: Nada
- */
- void MF_EscribeTexto(void)
- {
- MoveTo(30,30);
- DrawString("\pMacFormat - C de Cerca nº 3");
-
- }